home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 August: Tool Chest / Dev.CD Aug 98 TC.toast / Sample Code / Processes / ProcDoggie2.1b2 / UDialogUtils.p < prev    next >
Encoding:
Text File  |  1997-11-03  |  26.6 KB  |  666 lines  |  [TEXT/CWIE]

  1. UNIT UDialogUtils;
  2.  
  3. {-------------------------------------------------------------------------------
  4.     File:        UDialogUtils.p
  5.  
  6.     Contains:    Dialog utilities.
  7.  
  8.     Written by:    Forrest Tanaka
  9.  
  10.     Copyright:    © 1988-1997 by Apple Computer, Inc., all rights reserved.
  11.  
  12.     Change History (most recent first):
  13.  
  14.     You may incorporate this sample code into your applications without
  15.     restriction, though the sample code has been provided "AS IS" and the
  16.     responsibility for its operation is 100% yours.  However, what you are
  17.     not permitted to do is to redistribute the source as "DSC Sample Code"
  18.     after having made changes. If you're going to re-distribute the source,
  19.     we require that you make it clear in the source that the code was
  20.     descended from Apple Sample Code, but that you've made changes.
  21. --------------------------------------------------------------------------------
  22. #
  23. # This unit is an embryonic version of an alternative to the Dialog Manager.
  24. # Why replace the Dialog Manager?  For dialogs with just a few basic items like
  25. # some static text and some buttons, the Dialog Manager isn’t too bad.  It still
  26. # doesn’t handle low-memory situations at all well nor does it handle cases in
  27. # which some resources are missing with much grace, but a small dialog shouldn’t
  28. # have too many problems with low-memory situations and clever memory
  29. # management can avoid all problems, and missing resources is an anomalous
  30. # situation.  The Dialog Manager exposes its problems once a dialog starts to
  31. # get a bit complicated.  User items and controls become difficult to manage,
  32. # and even something as simple as a static text item that’s in a different size
  33. # or style becomes a major hassle to implement.  The ictb mechanism introduced
  34. # on Color QuickDraw machines was supposed to make it easier to specify static
  35. # and edit text styles, but this mechanism is so buggy that it’s useless in my
  36. # opinion.  Another problem with the Dialog Manager is its slow performance when
  37. # drawing items.  Technical Note #203 “Don’t Abuse the Managers” has many words
  38. # of wisdom when it comes to the Dialog Manager, like don’t use it.
  39. #
  40. # Of course, the usual reply we get to this is, “But ResEdit’s DITL editor makes
  41. # arranging dialogs so easy!”  This is true, and I think it’s a compelling
  42. # argument.  This also makes localization very easy, which isn’t a trivial
  43. # concern.  But who said that only the Dialog Manager can read DITLs?  The
  44. # structure of a DITL is very well-defined, and couldn’t possibly change without
  45. # breaking every program that put up an alert box.  DITL resources aren’t that
  46. # complicated, and your own program can read them as well as the Dialog
  47. # Manager——better probably.
  48. #
  49. # That’s what this unit does.  It reads in a DITL, creates an internal item list
  50. # based on what it found in the DITL, then attaches this item list to the
  51. # "items" field of a DialogRecord.  This unit also contains routines to draw the
  52. # items and routines to set static text items.  And it does this while checking
  53. # for errors; what a concept!
  54. #
  55. # But, as I said, this unit is very embryonic.  The first time I tried this, I
  56. # made it very complete, but I also made it much, much harder to use than the
  57. # Dialog Manager.  So, I almost completely stripped it for the purposes of this
  58. # sample application.  Now, it only handles static text items and buttons, and
  59. # it no longer handles modal dialogs.  Eventually, I want to give this the full
  60. # functionality of the real Dialog Manager.
  61. #
  62. # One capability this unit has that the Dialog Manager doesn’t implement is
  63. # style information for static text items.  I don’t mean one static text item
  64. # with multiple text styles.  I mean different items can have different text
  65. # styles.  Doing this through the Dialog Manager involves much more work than
  66. # it should.  The way I do this while keeping the DITL structure is to use the
  67. # four bytes used for a placeholder for handle or procedure pointer in Inside
  68. # Macintosh I page 427.  If you want static text items displayed in the standard
  69. # font, style, and justification, then just leave these four bytes set to 0.  If
  70. # you want to specify the type face, style, size, and line justification, then
  71. # each of these four bytes can hold each of these pieces of information.
  72. #
  73. # The first byte holds a font index.  This isn’t a font number because, as
  74. # Technical Note #191 “Font Names” says, it isn’t nice to save font numbers.
  75. # This font index is an index into a STR# resource which contains the names of
  76. # whatever fonts you want to use in this dialog.  For example, if the second
  77. # string in the STR# resource is "Monaco", then a 2 placed into the font index
  78. # field will cause the DrawDialogItems routine defined in this unit to display
  79. # that static text item in Monaco.  The STR# resource should have a resource ID
  80. # of 0.  This lets all dialog boxes use the same font list.  You can override
  81. # this font list by specifying a STR# resource with an ID equal to the resource
  82. # ID of the DITL being read.  In this way, you can provide a STR# resource ID 0
  83. # that contains the default font list, and then provide special font lists for
  84. # for specific DITLs.
  85. #
  86. # The second byte holds the style (“face” according to QuickDraw) of the static
  87. # text item.  This holds the same value as the Style type.  The third byte
  88. # contains the point size of the static text.  The point size is limited to 255,
  89. # which shouldn’t be a problem.  The last byte contains the justification of the
  90. # static text.  -2 means left justification, -1 means right justification, 0
  91. # means default justification, and 1 means center justification.
  92. #
  93. -------------------------------------------------------------------------------}
  94. {[j=20/57/1$] Pasmat Options}
  95.  
  96.  
  97. INTERFACE
  98.  
  99.     USES
  100.         Dialogs
  101.         ;
  102.  
  103. (*******************************************************************************
  104. * Used Units
  105. *******************************************************************************)
  106.  
  107. (*******************************************************************************
  108. * Constants
  109. *******************************************************************************)
  110.  
  111.     CONST
  112.         kNoItem = -1; {No dialog item is applicable or end of dialog item list}
  113.  
  114.  
  115. (*******************************************************************************
  116. * Types
  117. *******************************************************************************)
  118.  
  119.     TYPE
  120.         (* Type information for static text items *)
  121.         TypeInfoRec = RECORD
  122.             typeFace:  Integer; {Font number of text}
  123.             typeSize:  Integer; {Font size of text}
  124.             textJust:  Integer; {Justification of text}
  125.             typeStyle: Style;   {Font style of text}
  126.         END;
  127.  
  128.  
  129. (*******************************************************************************
  130. * InstallDialogItems - Install a DITL into a dialog window
  131. *
  132. * This routine is called to install a DITL into the dialog window specified by
  133. * "aDialog".  The resource ID of the desired DITL is specified by "itemListNum".
  134. * InstallDialogItems returns noErr if the item list was successfully created and
  135. * attached to aDialog, otherwise, an operating system error code is returned.
  136. *******************************************************************************)
  137.  
  138.     FUNCTION InstallDialogItems (aDialog:     DialogPtr;
  139.                                  itemListNum: Integer): OSErr;
  140.  
  141.  
  142. (*******************************************************************************
  143. * SetStatTextItem - Set a static text dialog item to the specified text
  144. *
  145. * This routine sets the text of a static text item to the text pointed to by
  146. * "textPtr" and having the length "textLength".  "aDialog" is a pointer to the
  147. * dialog box that this is being done in, and "itemNum" is the item number of the
  148. * static text item to set.  If that item isn’t actually a static text item, then
  149. * nothing is done.  If there isn’t enough memory to put the text into the static
  150. * text item, then nothing is done.
  151. *******************************************************************************)
  152.  
  153.     PROCEDURE SetStatTextItem (aDialog:    DialogPtr;
  154.                                itemNum:    Integer;
  155.                                textPtr:    Ptr;
  156.                                textLength: Integer);
  157.  
  158.  
  159. (*******************************************************************************
  160. * GetStatTextFontInfo - Get font information for a static text item
  161. *
  162. * This routine gets the font information for the static text item with an item
  163. * number of "itemNum" in the dialog specified by "aDialog".  This font
  164. * information is returned in "typeInfo".  The the specified item isn’t a static
  165. * text item, then nothing is done.
  166. *******************************************************************************)
  167.  
  168.     PROCEDURE GetStatTextFontInfo (aDialog:      DialogPtr;
  169.                                    itemNum:      Integer;
  170.                                    VAR typeInfo: TypeInfoRec);
  171.  
  172.  
  173. (*******************************************************************************
  174. * DrawDialogItems - Draw all standard dialog items
  175. *
  176. * All standard dialog items in the dialog box pointed to by "aDialog" are drawn.
  177. *******************************************************************************)
  178.  
  179.     PROCEDURE DrawDialogItems (aDialog: DialogPtr);
  180.  
  181.  
  182. (*******************************************************************************
  183. * GetDialogItemRect - Get the item rectangle of a specified dialog item
  184. *
  185. * This routine gets the item rectangle of the dialog item in the dialog box
  186. * specified by "aDialog" and having an item number of "itemNum".  This rectangle
  187. * is returned in "itemRect".
  188. *******************************************************************************)
  189.  
  190.     PROCEDURE GetDialogItemRect (aDialog:      DialogPtr;
  191.                                  itemNum:      Integer;
  192.                                  VAR itemRect: Rect);
  193.  
  194.  
  195. (*******************************************************************************
  196. * DisposeDialogItems - Dispose of all dialog items in the specified dialog box
  197. *
  198. * This routine disposes of the memory used by all the dialog items in the dialog
  199. * box specified by "aDialog".  The item list itself is also deallocated.
  200. *******************************************************************************)
  201.  
  202.     PROCEDURE DisposeDialogItems (aDialog: DialogPtr);
  203.  
  204.  
  205. IMPLEMENTATION
  206.  
  207.     USES
  208.         Resources
  209.         ,TextUtils
  210.         ,Fonts
  211.         
  212.         (* Application *)
  213.         ,UEmergMem
  214.         ;
  215.  
  216.  
  217. (*******************************************************************************
  218. * Types
  219. *******************************************************************************)
  220.  
  221.     TYPE
  222.         TextStRec = PACKED RECORD
  223.             fontIndex: Byte;       {Index into STR# rsrc of font name for text}
  224.             statStyle: Style;       {Style of static text}
  225.             statSize:  Byte;       {Point size of static text}
  226.             statJust:  SignedByte; {Justification of static text}
  227.         END;
  228.  
  229.         DITLTmplRec = PACKED RECORD
  230.             pad0:        TextStRec;  {Text style for static text items}
  231.             displayRect: Rect;       {Rect in which to display item in wind coords}
  232.             itemType:    Byte;       {Type of item}
  233.             dataLen:     Byte;       {Length of item data}
  234.             CASE Integer OF
  235.                 0: (itemRes:  Integer);
  236.                 1: (itemText: PACKED ARRAY [0..239] OF Char)
  237.         END;
  238.         DITLTmplPtr = ^DITLTmplRec;
  239.  
  240.         ItemRec = RECORD
  241.             displayRect: Rect;        {Display item rect in window coords}
  242.             refCon:      LongInt;     {Used for anything client wants}
  243.             dismissor:   Boolean;     {True if the item is a dismissor}
  244.             CASE itemType: Integer OF {Code for item type or 0 if last item}
  245.                 0: (itemControl:  ControlHandle); {Handle to item control}
  246.                 1: (itemText:     Handle;         {Handle to text of static text}
  247.                      itemTypeInfo: TypeInfoRec)    {Type info for static text}
  248.         END;
  249.         ItemListArr = ARRAY [0..255] OF ItemRec;
  250.         ItemListPtr = ^ItemListArr;
  251.         ItemListHnd = ^ItemListPtr;
  252.  
  253.  
  254. {$S DialogUtils}
  255. (*******************************************************************************
  256. * Public: InstallDialogItems
  257. *
  258. * This routine is mainly a DITL-resource interpreter.  After loading the DITL
  259. * resource with a resource ID passed in itemListNum into memory, it reads the
  260. * information in it to build up an array of dialog items in an ItemListArr,
  261. * which is defined in the TYPE section of this source file.  This routine
  262. * allocates the item array and attaches it to the "items" field of the specified
  263. * DialogRecord.  Once the item array is filled, the DITL is no longer needed and
  264. * is made purgeable.
  265. *
  266. * Currently, this routine handles push buttons and static text fields.  Push
  267. * buttons are simply handled by calling NewControl.  The resulting ControlHandle
  268. * is placed into the itemControl field of the ItemRec.  For static text items,
  269. * a handle to the text is placed into itemText and the style information is
  270. * placed into the itemTypeInfo.
  271. *
  272. * Static text items are handled a little differently, and involves a change to
  273. * the DITL structure.  I’ve kept the size of the DITL the same as it ever was,
  274. * but the four bytes that are described as a “placeholder for handle or
  275. * procedure pointer” on page 427 of Inside Macintosh I are now interpreted by
  276. * InstallDialogItems to hold font information for static text items.  This font
  277. * information has the structure described by TextStRec which is declared in the
  278. * TYPE section of this source file.  This is a four-byte record that holds the
  279. * type face, type style, type size, and justification (really alignment) of the
  280. * static text item.  InstallDialogItems converts this into a TypeInfoRec
  281. * (declared in the UDialogUtils.p file) which is then placed into the item
  282. * array.  When DrawDialogItems is called, it draws static text items using this
  283. * font information.
  284. *
  285. * The TextStRec consists of four bytes.  The first bytes specifies the type
  286. * face to use for the static text.  It doesn’t specify the font number because
  287. * font numbers for a particular type face can vary from system to system.
  288. * Instead, this field holds an index into a STR# resource which holds a list of
  289. * font names.  The STR# resource must have a resource ID equal to the resource
  290. * ID of the DITL being read, that is, "itemListNum."
  291. *
  292. * The second byte specifies the style that the static text is meant to be drawn
  293. * in.  It holds the same value as the Style type.  The Style type is 16 bits
  294. * wide, so I declared this field as a Byte instead.  The third byte specifies
  295. * the size of text to use.  Of course, being a byte, it’s limited to a point
  296. * size of 255 points.  I didn’t think that’d be much of a problem, and you can
  297. * always draw the text yourself if you needed something larger.  The last byte
  298. * specifies the alignment of text in the static text item rectangle.  This field
  299. * can have the values teFlushRight, teFlushLeft, teFlushDefault, and teCenter.
  300. *
  301. * I wanted to keep the DITL mechanism so that Rez and particularly ResEdit could
  302. * still be used to edit the DITL, even though the Dialog Manager isn’t being
  303. * used with these kinds of dialogs.  Unfortunately, I had to redefine the Rez
  304. * DITL template so that it could take the static text font information, and
  305. * worse, ResEdit won’t edit DITLs that have non-zero values in the location that
  306. * I’m reading the font information.  So, keeping the DITL isn’t any particular
  307. * advantage over defining a completely new structure.  But, I’ll leave it this
  308. * ways for now.  There ARE other resource editors that might not be quite so
  309. * quick to criticize my DITLs.
  310. *
  311. * If all the dialog items were installed correctly, then noErr is returned.  If
  312. * any error happend, then the operating system result code is returned and the
  313. * dialog item list is disposed of, leaving aDialog unaffected.
  314. *******************************************************************************)
  315.  
  316.     FUNCTION InstallDialogItems (aDialog:     DialogPtr;
  317.                                  itemListNum: Integer): OSErr;
  318.  
  319.         TYPE
  320.             IntPtr = ^Integer;
  321.  
  322.         VAR
  323.             numItems:     Integer;       {Number of items in item list}
  324.             itemNum:      Integer;       {Item number of item we’re installing}
  325.             itemKind:     Integer;       {Type of the item}
  326.             fontNumber:   Integer;       {Font number of static text item}
  327.             ditlItemPtr:  DITLTmplPtr;   {Pointer to each item}
  328.             ditlList:     Handle;        {Handle to DITL resource}
  329.             itemList:     ItemListHnd;   {Handle to the item list}
  330.             aControl:     ControlHandle; {Handle to a control we’re installing}
  331.             aString:      Str255;        {String used for a couple of things}
  332.             staticText:   Handle;        {Handle to text for static text item}
  333.             dataLen:      Integer;       {Length of item data, rounded up to even}
  334.             doesDismiss:  Boolean;       {True if the item is a dismissor}
  335.  
  336.         PROCEDURE RecoverError (error: Integer);
  337.  
  338.         BEGIN
  339.             IF ditlList <> NIL THEN
  340.                 BEGIN
  341.                     HUnlock (ditlList);
  342.                     HPurge (ditlList)
  343.                 END;
  344.             IF itemList <> NIL THEN
  345.                 DisposeDialogItems (aDialog);
  346.             DialogPeek(aDialog)^.items := NIL;
  347.             InstallDialogItems := error;
  348.             EXIT (InstallDialogItems)
  349.         END;
  350.  
  351.     BEGIN
  352.         ditlList := NIL;
  353.         itemList := NIL;
  354.  
  355.         (* Grab the requested DITL resource *)
  356.         ditlList := GetResource ('DITL', itemListNum);
  357.         IF ditlList = NIL THEN
  358.             IF ResError = noErr THEN
  359.                 RecoverError (resNotFound)
  360.             ELSE
  361.                 RecoverError (ResError);
  362.  
  363.         (* Make sure we don’t lose it while we’re reading from it *)
  364.         HNoPurge (ditlList);
  365.  
  366.         (* Allocate item list; add 1 for flag record and 1 for numItems-1 adj *)
  367.         numItems := IntPtr(ditlList^)^;
  368.         itemList := ItemListHnd(NewHandleMargin (SIZEOF (ItemRec) * (numItems +
  369.                 2), kAllocApp, NOT kAllocClr));
  370.         IF itemList = NIL THEN
  371.             RecoverError (memFullErr);
  372.  
  373.         (* Fill with kNoItem items in case of error while building item list *)
  374.         FOR itemNum := 0 TO numItems + 1 DO
  375.             itemList^^ [itemNum].itemType := kNoItem;
  376.  
  377.         (* Put the item list into the dialog record *)
  378.         DialogPeek(aDialog)^.items := Handle(itemList);
  379.  
  380.         (* Point at the first item in the DITL *)
  381.         HLock (ditlList);
  382.         ditlItemPtr := DITLTmplPtr(ORD4(ditlList^) + SIZEOF (Integer));
  383.  
  384.         (* For each item in DITL, install into item list *)
  385.         FOR itemNum := 0 TO numItems DO
  386.             BEGIN
  387.                 (* Get the type of the item *)
  388.                 itemKind := ditlItemPtr^.itemType;
  389.  
  390.                 (* If itemDisable flag clear, item is a dismissor *)
  391.                 IF itemKind < 128 THEN
  392.                     doesDismiss := TRUE
  393.                 ELSE
  394.                     BEGIN
  395.                         doesDismiss := FALSE;
  396.                         itemKind := itemKind - 128
  397.                     END;
  398.  
  399.                 (* Grab the item information *)
  400.                 IF itemKind = ctrlItem + btnCtrl THEN
  401.                     BEGIN
  402.                         (* Copy control’s title to controlTitle *)
  403.                         BlockMoveData (@ditlItemPtr^.dataLen, @aString, ditlItemPtr^.
  404.                                 dataLen + 1);
  405.  
  406.                         (* Create the new control *)
  407.                         aControl := NewControl (aDialog, ditlItemPtr^.displayRect,
  408.                                 aString, TRUE, 0, 0, 0, pushButProc, 0);
  409.  
  410.                         (* Put the control’s handle into our item list *)
  411.                         itemList^^ [itemNum].itemType := itemKind;
  412.                         itemList^^ [itemNum].itemControl := aControl;
  413.  
  414.                         (* Bail if there’s not enough memory *)
  415.                         IF FailLowMemory (0) THEN
  416.                             RecoverError (memFullErr)
  417.                         ELSE IF aControl = NIL THEN
  418.                             IF (ResError = noErr) | (ResError = resNotFound) THEN
  419.                                 RecoverError (resNotFound)
  420.                             ELSE
  421.                                 RecoverError (ResError);
  422.  
  423.                         (* Put the control’s item number into the control’s refCon *)
  424.                         SetControlReference (aControl, itemNum)
  425.                     END
  426.                 ELSE IF itemKind = statText THEN
  427.                     BEGIN
  428.                         (* Allocate space for text *)
  429.                         staticText := NewHandleMargin (ditlItemPtr^.dataLen,
  430.                                 kAllocApp, NOT kAllocClr);
  431.  
  432.                         (* Put the control’s handle into our item list *)
  433.                         itemList^^ [itemNum].itemType := itemKind;
  434.                         itemList^^ [itemNum].itemText := staticText;
  435.  
  436.                         (* Bail if there’s not enough memory for the text *)
  437.                         IF staticText = NIL THEN
  438.                             RecoverError (memFullErr);
  439.  
  440.                         (* Copy DITL text to our text handle *)
  441.                         BlockMoveData (@ditlItemPtr^.itemText, staticText^, ditlItemPtr^.
  442.                                 dataLen);
  443.  
  444.                         (* Put a handle to the text into our item list *)
  445.                         aString [0] := CHR (0);
  446.                         IF ditlItemPtr^.pad0.fontIndex > 0 THEN
  447.                             BEGIN
  448.                                 GetIndString ((*<*)aString, itemListNum, ditlItemPtr^.
  449.                                         pad0.fontIndex);
  450.                                 IF aString [0] = CHR (0) THEN
  451.                                     GetIndString ((*<*)aString, 0, ditlItemPtr^.pad0.
  452.                                             fontIndex)
  453.                             END;
  454.                         IF aString [0] = CHR (0) THEN
  455.                             fontNumber := 0
  456.                         ELSE
  457.                             GetFNum (aString, (*<*)fontNumber);
  458.                         itemList^^ [itemNum].itemTypeInfo.typeFace := fontNumber;
  459.                         itemList^^ [itemNum].itemTypeInfo.typeSize := ditlItemPtr^.
  460.                                 pad0.statSize;
  461.                         itemList^^ [itemNum].itemTypeInfo.textJust := ditlItemPtr^.
  462.                                 pad0.statJust;
  463.                         itemList^^ [itemNum].itemTypeInfo.typeStyle :=
  464.                                 ditlItemPtr^.pad0.statStyle
  465.                     END
  466.                 ELSE
  467.                     itemList^^ [itemNum].itemType := itemKind;
  468.  
  469.                 (* Copy interesting characteristics to our item list *)
  470.                 WITH itemList^^ [itemNum] DO
  471.                     BEGIN
  472.                         (*WITH*)displayRect := ditlItemPtr^.displayRect;
  473.                         (*WITH*)refCon := 0;
  474.                         (*WITH*)dismissor := doesDismiss
  475.                     END;
  476.  
  477.                 (* Bump the pointer to the next item in the DITL *)
  478.                 dataLen := BAnd (ditlItemPtr^.dataLen + 1, $FFFE);
  479.                 ditlItemPtr := DITLTmplPtr(ORD4(@ditlItemPtr^.itemText) + dataLen)
  480.             END;
  481.  
  482.         (* Don’t need the dialog item list any more *)
  483.         HUnlock (ditlList);
  484.         HPurge (ditlList);
  485.     END;
  486.  
  487.  
  488. {$S DialogUtils}
  489. (*******************************************************************************
  490. * Public: SetStatTextItem
  491. *
  492. * The text of a static text item is specified by a handle to the text, so that
  493. * handle is resized to the new text length, if needed, and then the text is
  494. * simply BlockMoved in.
  495. *******************************************************************************)
  496.  
  497.     PROCEDURE SetStatTextItem (aDialog:    DialogPtr;
  498.                                itemNum:    Integer;
  499.                                textPtr:    Ptr;
  500.                                textLength: Integer);
  501.  
  502.         VAR
  503.             itemList:   ItemListHnd; {Handle to item list}
  504.             textHandle: Handle;      {Handle to the existing item text}
  505.  
  506.     BEGIN
  507.         (* Grab the item list from the dialog window’s refCon *)
  508.         itemList := ItemListHnd(DialogPeek(aDialog)^.items);
  509.  
  510.         (* If the item is indeed a static text item, then set it *)
  511.         IF itemList^^ [itemNum].itemType = statText THEN
  512.             BEGIN
  513.                 textHandle := itemList^^ [itemNum].itemText;
  514.                 IF NOT FailLowMemory (textLength) THEN
  515.                     BEGIN
  516.                         IF GetHandleSize (textHandle) <> textLength THEN
  517.                             SetHandleSize (textHandle, textLength);
  518.                         BlockMoveData (textPtr, textHandle^, textLength)
  519.                     END
  520.             END
  521.     END;
  522.  
  523.  
  524. {$S DialogUtils}
  525. (*******************************************************************************
  526. * Public: GetStatTextFontInfo
  527. *
  528. * Font information for a static text item is simply stored in its itemTypeInfo
  529. * field.  It’s a simple matter of copying this record into "typeInfo".
  530. *******************************************************************************)
  531.  
  532.     PROCEDURE GetStatTextFontInfo (aDialog:      DialogPtr;
  533.                                    itemNum:      Integer;
  534.                                    VAR typeInfo: TypeInfoRec);
  535.  
  536.         VAR
  537.             itemList: ItemListHnd; {Handle to item list}
  538.  
  539.     BEGIN
  540.         (* Grab the item list from the dialog window’s refCon *)
  541.         itemList := ItemListHnd(DialogPeek(aDialog)^.items);
  542.  
  543.         (* If the item is indeed a static text item, then set it *)
  544.         IF itemList^^ [itemNum].itemType = statText THEN
  545.             typeInfo := itemList ^^ [itemNum].itemTypeInfo
  546.     END;
  547.  
  548.  
  549. {$S DialogUtils}
  550. (*******************************************************************************
  551. * Public: DrawDialogItems
  552. *
  553. * The item list of a dialog box is stored in the "items" field of the
  554. * DialogRecord.  This routine loops through every dialog item and draws whatever
  555. * item types it understands.  Currently, this is static text items and icons.
  556. *******************************************************************************)
  557.  
  558.     PROCEDURE DrawDialogItems (aDialog: DialogPtr);
  559.  
  560.         VAR
  561.             itemNum:    Integer;     {Item number of item we’re installing}
  562.             itemList:   ItemListHnd; {Handle to the item list}
  563.             itemRect:   Rect;        {Rectangle of dialog item}
  564.             staticText: Handle;      {Handle to static text}
  565.  
  566.     BEGIN
  567.         (* Draw any static text items or icon items in the item list*)
  568.         itemList := ItemListHnd(DialogPeek(aDialog)^.items);
  569.         itemNum := 0;
  570.         WHILE itemList^^ [itemNum].itemType <> kNoItem DO
  571.             BEGIN
  572.                 IF itemList^^ [itemNum].itemType = statText THEN
  573.                     BEGIN
  574.                         (* Item is a static text item; call TETextBox if there’s text *)
  575.                         staticText := itemList^^ [itemNum].itemText;
  576.                         IF GetHandleSize (staticText) > 0 THEN
  577.                             BEGIN
  578.                                 TextFont (itemList^^ [itemNum].itemTypeInfo.typeFace);
  579.                                 TextSize (itemList^^ [itemNum].itemTypeInfo.typeSize);
  580.                                 TextFace (itemList^^ [itemNum].itemTypeInfo.typeStyle);
  581.                                 itemRect := itemList^^ [itemNum].displayRect;
  582.                                 HLock (staticText);
  583.                                 TETextBox (staticText^, GetHandleSize (staticText),
  584.                                         itemRect, itemList^^ [itemNum].itemTypeInfo.
  585.                                         textJust);
  586.                                 HUnlock (statictext)
  587.                             END
  588.                     END;
  589.                 itemNum := itemNum + 1
  590.             END
  591.     END;
  592.  
  593.  
  594. {$S DialogUtils}
  595. (*******************************************************************************
  596. * Public: GetDialogItemRect
  597. *
  598. * The item list of a dialog box is in the "items" field of the DialogRecord.
  599. * This handle is retrieved and the displayRect of the specified item into
  600. * "itemRect".
  601. *******************************************************************************)
  602.  
  603.     PROCEDURE GetDialogItemRect (aDialog:      DialogPtr;
  604.                                  itemNum:      Integer;
  605.                                  VAR itemRect: Rect);
  606.  
  607.         VAR
  608.             itemList: ItemListHnd; {Handle to item list}
  609.  
  610.     BEGIN
  611.         (* Grab the item list from the dialog window’s refCon *)
  612.         itemList := ItemListHnd(DialogPeek(aDialog)^.items);
  613.  
  614.         (* Copy the item’s display rectangle *)
  615.         itemRect := itemList^^ [itemNum].displayRect
  616.     END;
  617.  
  618.  
  619. {$S DialogUtils}
  620. (*******************************************************************************
  621. * Public: DisposeDialogItems
  622. *
  623. * A handle to the dialog box’s dialog item list is retrieved from the
  624. * DialogRecord’s "items" handle.  The type of each item is checked, and the
  625. * memory taken by that item is disposed of appropriately.
  626. *******************************************************************************)
  627.  
  628.     PROCEDURE DisposeDialogItems (aDialog: DialogPtr);
  629.  
  630.         VAR
  631.             itemNum:  Integer;     {Item number of item we’re installing}
  632.             itemList: ItemListHnd; {Handle to the item list}
  633.  
  634.     BEGIN
  635.         (* Grab the item list from the dialog window’s refCon *)
  636.         itemList := ItemListHnd(DialogPeek(aDialog)^.items);
  637.  
  638.         (* Starting at item 1, go through entire list and dispose of each item *)
  639.         IF itemList <> NIL THEN
  640.             BEGIN
  641.                 itemNum := 0;
  642.                 WHILE itemList^^ [itemNum].itemType <> kNoItem DO
  643.                     BEGIN
  644.                         WITH itemList^^ [itemNum] DO
  645.                             BEGIN
  646.                                 IF (*WITH*)itemType = ctrlItem + btnCtrl THEN
  647.                                     BEGIN
  648.                                         IF (*WITH*)itemControl <> NIL THEN
  649.                                             DisposeControl ((*WITH*)itemControl)
  650.                                     END
  651.                                 ELSE IF (*WITH*)itemType = statText THEN
  652.                                     BEGIN
  653.                                         IF (*WITH*)itemText <> NIL THEN
  654.                                             DisposeHandle ((*WITH*)itemText)
  655.                                     END
  656.                             END;
  657.  
  658.                         (* Go on to the next item in the item list *)
  659.                         itemNum := itemNum + 1
  660.                     END;
  661.                 DisposeHandle (Handle(itemList))
  662.             END
  663.     END;
  664.  
  665. END.
  666.